package com.herench.bunch.cmis.core;


import com.herench.bunch.commons.annotation.Handler;
import com.herench.bunch.commons.support.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

import javax.annotation.PostConstruct;

/**
 * Created by ThinkPad on 2017/11/12.
 */


@Component
public class DefaultMessageProcessor implements MessageProcessor {

    private static final Logger logger = LoggerFactory.getLogger(DefaultMessageProcessor.class);


    @Autowired
    private ApplicationContext applicationContext;
    private ServicePool<String, MessageHandler> messageHandlerServicePool;
    private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();


    @Value("${handlerScanBasePackage}")
    private String basePackage ;
    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
    private String resourcePattern = DEFAULT_RESOURCE_PATTERN;
    private MetadataReaderFactory metadataReaderFactory;

    @Value("${hisDbUrl}")
    private String hisDbUrl;

    @Value("${hisUsername}")
    private String hisUsername;

    @Value("${hisPassword}")
    private String hisPassword;

    @Value("${exeSql}")
    private String exeSql;

    @PostConstruct
    public void init() throws Exception {
        if (logger.isInfoEnabled()) {
            logger.debug("init message processor......");
        }
        messageHandlerServicePool = new SimpleMessageHandlerServicePool();
        this.metadataReaderFactory = new CachingMetadataReaderFactory();

        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern;
        Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
        for (Resource resource : resources) {
            if (resource.isReadable()) {
                MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
                if (annotationMetadata.hasAnnotation(Handler.class.getName())) {
                    String className = metadataReader.getClassMetadata().getClassName();
                    Class<MessageHandler> handlerClass = (Class<MessageHandler>) Class.forName(className);
                    MessageHandler handler = applicationContext.getBean(handlerClass);
                    Handler annotation = handlerClass.getDeclaredAnnotation(Handler.class);
                    MessageConvert convert = (MessageConvert)annotation.messageConvertClass().getConstructor().newInstance();
                    handler.setMsgCode(annotation.code());
                    handler.setHandlerName(annotation.name());
                    handler.setMessageConvert(convert);
                    this.messageHandlerServicePool.release(annotation.code(), handler);
                }
            }
        }
    }


    @Override
    public ResponseMessage handler(RequestMessage requestMessage) throws Exception {
        ResponseMessage responseMessage = null;
        MessageHandler handler = null;
        String msgCode = requestMessage.getMsgCode();
        Assert.hasLength(msgCode, "msgCode 参数为空.");
        handler = messageHandlerServicePool.acquire(msgCode);
        if (handler == null) {
            throw new RuntimeException(msgCode + "所对应的handler没注册.");
        }
        responseMessage = handler.handler(requestMessage);
        return responseMessage;
    }


    protected String resolveBasePackage(String basePackage) {
        return ClassUtils.convertClassNameToResourcePath(basePackage);
    }
}
